package com.msg.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.msg.core.enums.FileStatusEnum;
import com.msg.core.util.JsonUtil;
import com.msg.domain.model.SysFile;
import com.msg.domain.model.SysFilePart;
import com.msg.mapper.SysFileMapper;
import com.msg.service.SysFilePartService;
import com.msg.service.SysFileService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.hash.HashInfo;
import org.dromara.x.file.storage.core.recorder.FileRecorder;
import org.dromara.x.file.storage.core.upload.FilePartInfo;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
@Slf4j
@RequiredArgsConstructor
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements SysFileService, FileRecorder {

    private final SysFilePartService sysFilePartService;

    @Override
    @SneakyThrows
    public boolean save(FileInfo fileInfo) {
        SysFile file= toSysFile(fileInfo);
        file.setFileStstus(FileStatusEnum.TMP.getCode());
        boolean boo=save(file);
        if(boo){
            fileInfo.setId(file.getId());
        }
        log.info("文件上传成功:[{}]", JsonUtil.toJsonString(fileInfo));
        return boo;
    }

    @SneakyThrows
    @Override
    public void update(FileInfo fileInfo) {
        SysFile sysFile=toSysFile(fileInfo);
        if(sysFile!=null){
            saveOrUpdate(sysFile);
        }
    }

    @SneakyThrows
    @Override
    public FileInfo getByUrl(String url) {
        SysFile file=getOne(new LambdaQueryWrapper<SysFile>().eq(SysFile::getUrl,url));
        return toFileInfo(file);
    }

    @SneakyThrows
    @Override
    public FileInfo getByFileId(Long fileId) {
        SysFile file=getById(fileId);
        return toFileInfo(file);
    }

    @Override
    public boolean delete(String url) {
        SysFile file=getOne(new LambdaQueryWrapper<SysFile>().eq(SysFile::getUrl,url));
        if(file!=null){
            file.setFileStstus(FileStatusEnum.DEL.getCode());
        }
        log.info("文件删除成功:[{}]",JsonUtil.toJsonString(url));
        return saveOrUpdate(file);
    }
    @SneakyThrows
    @Override
    public void saveFilePart(FilePartInfo filePartInfo) {
        SysFilePart part=toSysFilePart(filePartInfo);
        if (sysFilePartService.save(part)) {
            filePartInfo.setId(part.getId());
        }
    }

    @Override
    public void deleteFilePartByUploadId(String uploadId) {
        sysFilePartService.remove(new LambdaQueryWrapper<SysFilePart>().eq(SysFilePart::getUploadId, uploadId));
    }

    /**
     * 将 FileInfo 转为 SysFile
     */
    private SysFile toSysFile(FileInfo info) throws JsonProcessingException {
        SysFile file = BeanUtil.copyProperties(
                info, SysFile.class, "metadata", "userMetadata", "thMetadata", "thUserMetadata", "attr", "hashInfo");
        // 这里手动获 元数据 并转成 json 字符串，方便存储在数据库中
        file.setMetadata(JsonUtil.toJsonString(info.getMetadata()));
        file.setUserMetadata(JsonUtil.toJsonString(info.getUserMetadata()));
        file.setThMetadata(JsonUtil.toJsonString(info.getThMetadata()));
        file.setThUserMetadata(JsonUtil.toJsonString(info.getThUserMetadata()));
        // 这里手动获 取附加属性字典 并转成 json 字符串，方便存储在数据库中
        file.setAttr(JsonUtil.toJsonString(info.getAttr()));
        // 这里手动获 哈希信息 并转成 json 字符串，方便存储在数据库中
        file.setHashInfo(JsonUtil.toJsonString(info.getHashInfo()));
        return file;
    }

    /**
     * 将 FileDetail 转为 FileInfo
     */
    private FileInfo toFileInfo(SysFile file) throws JsonProcessingException {
        if(file==null){
            return null;
        }
        FileInfo info = BeanUtil.copyProperties(
                file, FileInfo.class, "metadata", "userMetadata", "thMetadata", "thUserMetadata", "attr", "hashInfo");

        // 这里手动获取数据库中的 json 字符串 并转成 元数据，方便使用
        info.setMetadata(jsonToMetadata(file.getMetadata()));
        info.setUserMetadata(jsonToMetadata(file.getUserMetadata()));
        info.setThMetadata(jsonToMetadata(file.getThMetadata()));
        info.setThUserMetadata(jsonToMetadata(file.getThUserMetadata()));
        // 这里手动获取数据库中的 json 字符串 并转成 附加属性字典，方便使用
        info.setAttr(JsonUtil.toObject(file.getAttr(), Dict.class));
        // 这里手动获取数据库中的 json 字符串 并转成 哈希信息，方便使用
        info.setHashInfo(JsonUtil.toObject(file.getHashInfo(), HashInfo.class));
        return info;
    }


    /**
     * 将 json 字符串转换成元数据对象
     */
    private Map<String, String> jsonToMetadata(String json) throws JsonProcessingException {
        if (StrUtil.isBlank(json)) {
            return null;
        }
        return JsonUtil.toCollection(json, new TypeReference<Map<String, String>>() {});
    }


    /**
     * 将 FilePartInfo 转为 SysFilePart
     *
     */
    public SysFilePart toSysFilePart(FilePartInfo info) throws JsonProcessingException {
        SysFilePart part = new SysFilePart();
        part.setPlatform(info.getPlatform());
        part.setUploadId(info.getUploadId());
        part.setETag(info.getETag());
        part.setPartNumber(info.getPartNumber());
        part.setPartSize(info.getPartSize());
        part.setHashInfo(JsonUtil.toJsonString(info.getHashInfo()));
        part.setCreateTime(info.getCreateTime());
        return part;
    }

}
